//前端专属的工具函数 （后端专属的工具在app\api\util）
import { type ClassValue, clsx } from "clsx"
import { CSSProperties, ReactNode } from "react"
import { twMerge } from "tailwind-merge"
import { message as AntdMessage } from 'antd';
import { NoticeType } from "antd/es/message/interface";
import ReactMarkdown from "react-markdown";

/**合并css类名
 * @param inputs 要合并的类名
 * @returns 
 */
export function cn(...inputs: ClassValue[]) {
    return twMerge(clsx(inputs))
}
/**合并style
 * @param inputs 要合并的style
 */
export function sn(...inputs: CSSProperties[]) {
    return Object.assign({}, ...inputs)
}
/**使用antd做弹窗，展示信息 - 仅前端 - 仅客户端"use client";
 * @param content 要提示的文字，或者一个ReactNode
 * @param type 类型，默认"success"。 
 * @param duration 显示时间，单位s，默认2s ，0代表不关闭
 * @param key 每个message唯一的key， 可以用于destroy。默认为当前时间戳
 * @returns 返回弹窗实例，可以进行.then等
 */
export function showTip(content: ReactNode | string, type: NoticeType = 'success', duration: number = 2, key: any = new Date().getTime()) {
    return AntdMessage.open({
        type,
        content,
        duration,
        key,
        style: { zIndex: 99999 }
    })
}
/**基于showTip，展示markdown格式的弹窗 */
export function showMdTip(content: string, type?: NoticeType, duration?: number, key?: any) {
    showTip(ReactMarkdown({ children: content }), type, duration, key)
}
/**删除antd弹窗
 * @param key 要删除的key，不填代表全部
 */
export function destroyTip(key?: any) {
    AntdMessage.destroy(key)
}

/**获取file的base64 */
export function getBase64(file: File) {
    return new Promise<string>(async (resolve, reject) => {
        try {
            // 创建FileReader对象
            const reader = new FileReader();
            // 文件读取完成时的回调函数
            reader.onloadend = async function () {
                resolve(reader.result as string) // 读取完成后的结果为Base64编码的字符串 
            };
            reader.readAsDataURL(file); // 读取文件并将其转换为Base64编码
        } catch (error) {
            reject(error)
        }
    })

}

/**创建a链接，下载文件（如果是图片或视频可能不合适用这个）
 * @param url 文件url 
 * @param name 文件名字，带后缀。可能无法正确设置。 
 */
export function download(url: string, name?: string) {
    if (!url) {
        showTip("请正确传递url", 'error')
        return
    }
    showTip("正在下载，请稍后", 'loading')
    const elt = document.createElement('a');
    elt.setAttribute('href', url);
    elt.setAttribute('download', name || 'file');
    elt.style.display = 'none';
    document.body.appendChild(elt);
    elt.click();
    document.body.removeChild(elt);
}

/**查找符合条件的父节点
 * @param node 当前节点。如果当前节点就符合条件，就会返回当前节点
 * @param target 参数是当前找到的节点，返回一个布尔值，为true代表找到想要的父节点
 * @returns 没找到则返回null，找到了返回Element
 */
export function findParent(node: Element, target: (nowNode: Element) => boolean) {
    while (node && !target(node)) {
        if (node.parentElement) {
            node = node.parentElement;
        } else {
            return null;
        }
    }
    return node;
}
/**读取文件内容。 */
export function readFile<T>(file: File, type: "readAsArrayBuffer" | "readAsBinaryString" | "readAsDataURL" | "readAsText") {
    return new Promise<T | undefined>((resolve, reject) => {
        try {
            const reader = new FileReader();
            reader.onload = function (e) {
                const contents = e.target?.result;
                resolve(contents as T | undefined);
            };
            reader.onerror = function (e) {
                console.log('读取文件出错', e);
                reject(new Error('读取文件出错'));
            };
            reader[type](file);
        } catch (error) {
            console.log('读取文件内容 运行失败', error);
            reject('运行失败')
        }
    });
}


/**超出长度截断字符串，可以添加末尾字符
 * @param str 字符串
 * @param maxLength 最大长度
 * @param tip 如果超出长度，末尾的提示字符
 * @returns 新字符串
 */
export const sliceStr = (str: string, maxLength: number, tip = '') => {
    if (str.length < maxLength) return str
    else return str.slice(0, maxLength) + tip
}



/**生成label和value一样的下拉框option，用于antd */
export const createOption = <T extends string | number>(valArr: T[]) => {
    return valArr.map((k) => ({ value: k, label: k }))
}